#ifndef __CMD_H_
#define __CMD_H_


#define __pack __attribute__ ((__packed__))
// DOORID: len 0x20
// RANDOM RSP: len 0x10

#define DOORID_LEN	0x20
#define RANDOM_NUM_LEN 0x10
//#define USERID_LEN 0x20

enum cmd_id {
	CMD_REQ_AUTH_REQ = 0x01,
	CMD_RSP_AUTH_ENQ = 0x02,
	CMD_REQ_AUTH_POLL = 0x03,
	CMD_RSP_AUTH_ACK_WAIT = 0x04,
	CMD_RSP_AUTH_ACK_KEY = 0x05,
	CMD_RSP_AUTH_RM_KEY = 0x06,


	CMD_REQ_DOORID = 0x10,
	CMD_RSP_DOORID = 0x11,
	CMD_REQ_RANDOM_NUM = 0x12,
	CMD_RSP_RANDOM_NUM = 0x13,
	CMD_REQ_ENCRYPT_RANDOM_NUM = 0x14,
	CMD_RSP_ENCRYPT_RANDOM_NUM = 0x15,
	CMD_REQ_DIGKEY_TOKEN = 0x16,
	CMD_RSP_DIGKEY_TOKEN = 0x17,
	CMD_REQ_PHONE_INFO = 0x18,
	CMD_RSP_PHONE_INFO = 0x19,
	CMD_REQ_OPENDOOR = 0x1A,
	CMD_RSP_OPENDOOR = 0x1B,

	CMD_REQ_BOX_ID = 0x30,
	CMD_RSP_BOX_ID = 0x31,
	CMD_REQ_BOX_AUTH_QUE = 0x32,
	CMD_RSP_BOX_AUTH_QUE = 0x33,
	CMD_REQ_BOX_AUTH_CONFIRM = 0x34,
	CMD_RSP_BOX_AUTH_CONFIRM = 0x35,
	
	CMD_MAX_NUM,
};

#define BT_ADDR_LEN		24
#define WIFI_ADDR_LEN	24
#define IMEI_LEN		24
#define USERID_LEN		4

enum token_type {
	TOKEN_TYPE_IMEI = 'M',
	TOKEN_TYPE_PUBKEY,
	TOKEN_TYPE_WMAC,
	TOKEN_TYPE_BMAC,
	TOKEN_TYPE_USERID,
};

/* common header */
struct cmd_hdr {
	uint8_t bType;
	uint32_t wLength;
	uint8_t data[0];
} __pack;

#define CMD_HDR_LEN		sizeof(struct cmd_hdr)

/* ---- starts of phone <-> box ----- */
struct req_auth_req {
	uint32_t dwUserID;
	uint8_t strIMEI[IMEI_LEN];
	uint8_t strBTAddress[BT_ADDR_LEN];
	uint8_t strMACAddress[WIFI_ADDR_LEN];
} __pack;

struct resp_auth_enq {
	uint8_t bResult;
	uint8_t bCause;
} __pack;

struct req_auth_poll {
	uint32_t dwUserID;
} __pack;

struct resp_auth_ack_wait {
	uint8_t bQueueStatus;
#define AUTH_ACK_STATUS_FATAL	0xA1
} __pack;

struct resp_auth_ack_key {
	uint32_t dwUserID;
	uint32_t dwCommID;
	uint32_t dwDoorID;
	uint8_t  strDoorDesc[64];
	uint8_t  strKeyToken[0]; // FIXME
} __pack;

struct resp_auth_ack_remove_key {
	uint32_t dwCommID;
	uint8_t  bDeAuthNum;
	uint32_t dwDoorID[0];
} __pack;

struct auth_token {
	uint8_t  bType;
#define AUTH_TOKEN_TYPE 0xEE
	uint32_t dwUserID;
	uint8_t  strIMEI[IMEI_LEN];
	uint8_t  strMACAddress[WIFI_ADDR_LEN];
	uint8_t  strBTAddress[BT_ADDR_LEN];
	uint32_t dwCommID;
	uint32_t dwDoorID;
	uint32_t dwReserve1;
	uint32_t dwReserve2;
	uint8_t  strUserPub[0];
#define AUTH_TOKEN_MAX_PUB_LEN	1024
} __pack;

/* ---- ends of phone <-> box ----- */


/* ---- starts of phone <-> door ----- */
struct resp_door_id {
	uint32_t dwCommID;
	uint32_t dwDoorID;
	uint8_t  bSubDoorNum;
} __pack;

struct resp_dig_token {
	uint8_t bKeyCheckError;
} __pack;

struct req_phone_info {
	uint32_t dwUserID;
	uint8_t  strIMEI[IMEI_LEN];
	uint8_t  strBTAddress[BT_ADDR_LEN];
	uint8_t  strMACAddress[WIFI_ADDR_LEN];
} __pack;

struct resp_phone_info {
	uint8_t bInfoCheckError;
#define INFO_ERROR_IMEI		0x01
#define INFO_ERROR_BT_ADDR	0x02
#define INFO_ERROR_WIFI_ADDR	0x04
} __pack;

#define RANDOM_NUMBER_SIZE	0x20	/* 32 bytes */

struct resp_random_encrypt {
	uint8_t bRandom;
#define RANDOM_SUCCESS	0
#define RANDOM_FAILED	1
} __pack;

struct req_open_door {
	uint8_t  bSubDoorID;
	uint16_t wRSSI;
} __pack;

struct resp_open_door {
	uint8_t bOpenResult;
#define OPENDOOR		1
#define DONTOPENDOOR	0
} __pack;


//#define  DOORID  0x12345678
#define  DOORID  0x0000000E
#define  COMMID  0x11223344
#define  BOXID   0x33445566


/*  ----- starts of pc <---> box --------- */
#define UKEYID   0x99887766

/* BOX_ID_REQ: pc -> box , embedded in cmd_hdr{} */
struct resp_box_id {
	uint8_t magic[9];
#define BOX_ID_MAGIC_CODE "ONE-STEP"
	uint32_t dwBoxID;
	uint32_t dwCommID;
	uint32_t dwUkeyID;
} __pack;

/* REQ_AUTH_QUE embedded in cmd_hdr{} */

struct resp_box_auth_item {
	uint32_t dwUserId;
	uint8_t  strIMEI[IMEI_LEN];
	uint8_t  strMACAddr[WIFI_ADDR_LEN];
	uint8_t  strBTAddr[BT_ADDR_LEN];
} __pack;

struct resp_box_auth_queue {
	uint8_t  bQSize;
	struct resp_box_auth_item items[0];
} __pack;

/*
 * data includes: 
 * doorid[0:bDoorAuthNum-1]
 * doorid[0:bDoorDeauthNum-1]
 * strUserKeyPub
 */
struct req_box_auth_confirm {
	uint32_t dwUserID;
	uint32_t dwCommID;
	uint8_t  bDoorAuthNum;
	uint8_t  bDoorDeauthNum;
	uint8_t  data[0];
} __pack;

struct resp_box_auth_confirm {
	uint8_t bAuthResult;
#define AUTH_RESULT_SUCC 0
#define AUTH_RESULT_PHONE_NO_RESPONSE 1
#define AUTH_RESULT_UNSPEC 2
} __pack;

#endif //__CMD_H_

